package com.example.compose.retrofit.updataApp

import android.os.Environment
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.compose.Constance
import com.example.compose.retrofit.NetWorkManager
import com.example.compose.utils.DataStoreManager
import com.example.compose.utils.FileUtils
import com.example.compose.utils.LogUtil
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch
import okhttp3.ResponseBody
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import java.io.BufferedInputStream
import java.io.RandomAccessFile
import java.net.UnknownHostException

class CheckUpdateViewModel: ViewModel() {

    private val status:DownloadStatus? = null

    private var call:Call<ResponseBody>? = null

    val downloadStatus = MutableStateFlow(status)

    fun pause() :Boolean{
        call?.cancel()
        return call?.isCanceled?:false
    }

    fun networkChangesFlow(){
        if(downloadStatus.value is DownloadStatus.DownloadProcess) {
            pause()
            downloadStatus.value = DownloadStatus.DownloadNetworkChangesFlow
        }
        if(downloadStatus.value is DownloadStatus.DownloadError){
            downloadStatus.value = DownloadStatus.DownloadNetworkChangesFlow
        }
    }


    fun download(
        url: String,
        start: Long? = null,
        contentLength: Long? = null,
        appVersionNumber: String?,
        localVersionNumber: String){
        if(downloadStatus.value is DownloadStatus.DownloadProcess && call?.isCanceled == false ) return
        if(downloadStatus.value !is DownloadStatus.DownloadProcess){
            downloadStatus.value = DownloadStatus.DownloadProcess(
                0,
                0,
                0f
            )
        }
        val file = FileUtils.makeFile("${Constance.AppInformation.appName()}.apk", type = Environment.DIRECTORY_DOWNLOADS)
        start?.let {
            file?.let { file->
                try {
                    if(it==contentLength && it!=0L && appVersionNumber == localVersionNumber){
                        if(FileUtils.getFileSize(file) != it) {
                            download(url,0,0,appVersionNumber, "0")
                        }else{
                            downloadStatus.value = DownloadStatus.DownloadSuccess(file)
                        }
                        return
                    }
                }catch (e:Exception){
                    e.printStackTrace()
                }
            }
        }
        try {
            call = NetWorkManager.getRequest().download( if(appVersionNumber == localVersionNumber) "bytes=$start-$contentLength" else "",url)
            LogUtil.d("开始下载${if(appVersionNumber == localVersionNumber) "bytes=$start-$contentLength" else ""}")
        }catch (e:UnknownHostException){
            downloadStatus.value = DownloadStatus.DownloadError(e)
            e.printStackTrace()
            return
        }
        call?.enqueue(object : Callback<ResponseBody>{
            override fun onResponse(call: Call<ResponseBody>, response: Response<ResponseBody>) {
                viewModelScope.launch(Dispatchers.IO) {
                    response.body()?.let { body ->
                        val length = body.contentLength() + (start?:0)
                        val ios = body.byteStream()
                        val rwd = try {
                            RandomAccessFile(file, "rwd")
                        } catch(e:Exception){
                            downloadStatus.value = DownloadStatus.DownloadError(e)
                            return@let
                        }
                        rwd.seek(if(appVersionNumber==localVersionNumber) start?:0 else 0)
                        var currentLength: Int = if(appVersionNumber==localVersionNumber) start?.toInt()?:0 else 0
                        val bufferSize = 1024 * 8
                        val buffer = ByteArray(bufferSize)
                        val bufferedInputStream = BufferedInputStream(ios, bufferSize)
                        var readLength: Int
                        try{
                            while (bufferedInputStream.read(buffer, 0, bufferSize)
                                    .also { readLength = it } != -1
                            ) {
                                rwd.write(buffer,  0, readLength)
                                currentLength += readLength
                                downloadStatus.value = DownloadStatus.DownloadProcess(
                                    currentLength.toLong(),
                                    length,
                                    currentLength.toFloat() / length.toFloat()
                                )
                            }
                            bufferedInputStream.close()
                            rwd.close()
                            ios.close()
                        }catch (e: Exception){
                            e.printStackTrace()
                            if(!call.isCanceled)
                                downloadStatus.value = DownloadStatus.DownloadError(e)
                            return@launch
                        }finally {
                            LogUtil.d("保存下载信息${currentLength.toLong()},$length,$appVersionNumber")
                            DataStoreManager.saveUpDataVersion(
                                "${currentLength.toLong()},$length,$appVersionNumber"
                            )
                        }
                        downloadStatus.value = DownloadStatus.DownloadSuccess(file)
                    } ?: kotlin.run {
                        downloadStatus.value = DownloadStatus.DownloadError(RuntimeException("下载出错"))
                    }
                }
            }

            override fun onFailure(call: Call<ResponseBody>, t: Throwable) {
                t.message?.let { LogUtil.d(it) }
                if(call.isCanceled) return
                downloadStatus.value = DownloadStatus.DownloadError(t)
            }


        })

    }



}